package com.yyl.fmall.user.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yyl.fmall.user.entity.User;
import com.yyl.fmall.user.exception.IllegalCharacterException;
import com.yyl.fmall.user.service.IUserService;
import com.yyl.fmall.utils.CommonConstants;
import com.yyl.fmall.utils.R;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * <p>
 * 用户  前端控制器
 * </p>
 *
 * @author YuanSir
 * @since 2022-11-03
 */
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {
    
    @Autowired
    private IUserService userService;
    
    @PostMapping("/regist")
    public R regist(@RequestBody User user){
        
        User returnUser = userService.regist(user);
        
        return R.ok().put("data", returnUser);
        
    }
    
    
    @GetMapping("/login")
    public R login(String username, String password) throws JsonProcessingException {
    
        //1.获取shiro的subject对象
        Subject subject = SecurityUtils.getSubject();
    
        try {
            subject.login(new UsernamePasswordToken(username, password));
        } catch (AuthenticationException e) {
            throw new IllegalCharacterException("用户名或者密码错误，登陆失败！");
        }
        
        //2.返回json
        User user = (User) subject.getPrincipal();
        
        //生成服务器端的token，用于后端的请求验证用户的身份
        String token = createToken(user);
        
        return R.ok(token).put("data", user);
    
    }
    
    
    
    
    /**
     * 创建token字符串
     * 对于token的需求
     * 1. 要能让服务器端校验token是否合法（是不是服务器端颁发的token）
     * 2. 时效性（能够指定过期时间）
     * 3. 扩展性（可以自定义存入token中的信息）
     * @param user
     * @return
     */
    private String createToken(User user) throws JsonProcessingException {
        
        //user ——> json
        ObjectMapper objectMapper = new ObjectMapper();
        String userJson = objectMapper.writeValueAsString(user);
    
        HashMap<String, Object> map = new HashMap<>();
        map.put(CommonConstants.JWT_CLAIMS_KEY, userJson);
    
        return Jwts.builder()
                .setClaims(map) //自定义数据
                .setSubject(user.getUsername())
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date())
                .setIssuer(CommonConstants.JWT_AUTHOR)
                .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60 * 60)))
                .signWith(SignatureAlgorithm.HS256, CommonConstants.JWT_SECRET_KEY)
                .compact();
    }
    
}
